﻿using LightCAD.Core;
using LightCAD.Runtime.Editor;
using SkiaSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Runtime.Creator
{
    public class CircleCreator : ElementCreator
    {
        public static string CmdName;
        public static CreateMethod[] Methods;
        public static CreateMethod DefaultMethod;
        static CircleCreator()
        {
            Methods = new CreateMethod[4];
            CmdName = "CIRCLE";
            var method0 = new CreateMethod();
            method0.Name = "CR";
            method0.Descr = "圆心半径画圆";
            method0.StepNames = new string[3];
            method0.StepOptions = new string[3];
            method0.StepNames[0] = "SpecifyCenter";
            method0.StepOptions[0] = "指定圆的圆心或[三点(3P) 二点(2P) 切点,切点,半径(T)]:";
            method0.StepNames[1] = "SpecifyRadius";
            method0.StepOptions[1] = "指定圆的半径或[直径(D)]:";
            method0.StepNames[2] = "SpecifyDiameter";
            method0.StepOptions[2] = "指定圆的直径:";
            Methods[0] = method0;
            DefaultMethod = method0;

            var method1 = new CreateMethod();
            method1.Name = "3P";
            method1.Descr = "三点画圆";
            Methods[1] = method1;

            var method2 = new CreateMethod();
            method2.Name = "2P";
            method2.Descr = "二点画圆";
            method2.StepNames = new string[2];
            method2.StepOptions = new string[2];
            method2.StepNames[0] = "SpecifyPoint1";
            method2.StepOptions[0] = "指定圆直径的第一个端点:";
            method2.StepNames[1] = "SpecifyPoint2";
            method2.StepOptions[1] = "指定圆直径的第二个端点:";

            Methods[2] = method2;

            var method3 = new CreateMethod();
            method3.Name = "T";
            method3.Descr = "切点切点半径画圆";
            Methods[3] = method3;


        }

        private Vector2d _center;
        private Vector2d _center_point;
        private Vector2d _point1;
        private Vector2d _point2;
        private Vector2d _point3;
        private Vector2d _tangent1;
        private Vector2d _tangent2;
        private string _methodName;
        private string _methodArg;

        public CircleCreator()
        {

        }
        public override string GetCmdName()
        {
            return CmdName;
        }
        public override CreateMethod[] GetMethods()
        {
            return CircleCreator.Methods;
        }


        protected override void ExecuteStep(CreateMethod method, string stepName, string stepArg)
        {
            var tip = GetStepTip(method, stepName);
            if (stepArg != null)
            {
                method = GetMethod(stepArg);
                stepName = method.StepNames[0];
                tip = tip + " " + stepArg + " " + GetStepTip(method, stepName);
            }
            _methodName = method.Name;
            if (method.Name == "CR")
            {
                if (stepName == "SpecifyCenter")
                {
                    CmdInputer.StartInput(tip, (succ, txt) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }
                        if (txt.ToUpper() == "2P")
                        {
                            var jumpMethod = GetMethod("2P");

                            ExecuteStep(jumpMethod, jumpMethod.StepNames[0], null);
                        }
                    });
                    VPortInputer.StartInputPoint((succ, p) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }
                        _center = p.Value;
                        var nextStep = GetNextStepName(method, stepName);
                        ExecuteStep(method, nextStep, null);

                    });
                }
                else if (stepName == "SpecifyRadius")
                {
                    VPortInputer.SetAuxLineDraw(AuxLineDraw);
                    CmdInputer.StartInput(tip, (succ, txt) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }
                        if (txt.ToUpper() == "D")
                        {
                            var nextStep = GetNextStepName(method, stepName);
                            ExecuteStep(method, nextStep, null);
                        }
                    });

                    VPortInputer.StartInputPoint((succ, p) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }
                        _center_point = p.Value;
                        CreateCircleElement();//----------------------------------------
                        ExecuteEnd(true);
                    });

                }
                else if (stepName == "SpecifyDiameter")
                {
                    CmdInputer.StartInput(tip, (succ, txt) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }
                        //TODO:
                    });

                    VPortInputer.StartInputPoint((succ, p) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }
                        _center_point = p.Value;
                        _methodArg = "D";
                        CreateCircleElement();//----------------------------------------
                        ExecuteEnd(true);
                    });
                }
            }

            else if (method.Name == "2P")
            {
                if (stepName == "SpecifyPoint1")
                {
                    CmdInputer.StartInput(tip, (succ, txt) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }

                    });
                    VPortInputer.StartInputPoint((succ, p) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }
                        _point1 = p.Value;
                        var nextStep = GetNextStepName(method, stepName);
                        ExecuteStep(method, nextStep, null);
                    });
                }
                else if (stepName == "SpecifyPoint2")
                {
                    VPortInputer.SetAuxLineDraw(AuxLineDraw);
                    CmdInputer.StartInput(tip, (succ, txt) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }
                        //TODO:
                    });

                    VPortInputer.StartInputPoint((succ, p) =>
                    {
                        if (!succ) { ExecuteEnd(false); return; }
                        _point2 = p.Value;
                        CreateCircleElement();//----------------------------------------
                        ExecuteEnd(true);
                    });
                }
            }
        }

        private void CreateCircleElement()
        {
            if (_methodName == "CR")
            {
                if (_methodArg == "D")
                    LcDocument.Current.ModelSpace.AddCircle(_center, Vector2d.Distance(_center_point, _center) / 2);
                else
                    LcDocument.Current.ModelSpace.AddCircle(_center, Vector2d.Distance(_center_point, _center));
            }
            else if (_methodName == "2P")
            {
                var c = (_point1 + _point2) / 2;
                var r = Vector2d.Distance(_point1, _point2) / 2;
                LcDocument.Current.ModelSpace.AddCircle(c, r);
            }
        }
        private void AuxLineDraw(SKCanvas canvas, params object[] args)
        {
            if (_methodName == "CR")
            {
                var movePoint = (SKPoint)args[0];
                var center = ElementDrawer.PointWorldToScr(_center);

                if (center == movePoint) return;

                using (var pen = new SKPaint { Color = SKColors.Silver, IsStroke = true })
                {
                    canvas.DrawLine(center, movePoint, pen);
                    var radius = (_methodArg == "D") ? SKPoint.Distance(center, movePoint) / 2 : SKPoint.Distance(center, movePoint);
                    canvas.DrawCircle(center, radius, pen);
                }
            }
            else if (_methodName == "2P")
            {
                var movePoint = (SKPoint)args[0];
                var p1 = ElementDrawer.PointWorldToScr(_point1);

                if (p1 == movePoint) return;

                using (var pen = new SKPaint { Color = SKColors.Silver, IsStroke = true })
                {
                    canvas.DrawLine(p1, movePoint, pen);
                    var cx = (p1.X + movePoint.X) / 2;
                    var cy = (p1.Y + movePoint.Y) / 2;
                    var r = SKPoint.Distance(p1, movePoint) / 2;
                    canvas.DrawCircle(cx,cy, r, pen);
                }
            }
        }
    }
}
